#pragma once

#include "SimpleVector2D.h"
#include "LinkedList.h"
#include "LinkedList.cpp"

using namespace SimpleVector2D;

// This is for defing what kind of shape
// our Physic Object will have.
typedef enum PHYSIC_OBJECT_TYPE{
	PHYSIC_OBJECT_TYPE_CIRCLE,
	PHYSIC_OBJECT_TYPE_SQUARE
} PHYSIC_OBJECT_TYPE;

// This is the Physic Object structure. 
// This object is used to create a Rigid Body
// by the Physic System. The Rigid Body and 
// Physic Object will be linked together by
// the Physic System. Any changes done to the 
// Physic Object will be "reflected" on 
// the Rigid Body.
struct PhysicObject{
	PHYSIC_OBJECT_TYPE m_physic_object_type;
	Vector2D m_position;
	Vector2D m_velocity;
	float m_radius;
	float m_width;
	float m_height;

	// This is the Contact List, a list of other Objects that
	// this Object has collide with. 
	LinkedList<PhysicObject **> m_PhysicObjectContactList;

	PhysicObject(){
		m_physic_object_type = PHYSIC_OBJECT_TYPE_CIRCLE;
		m_radius = 16.0f;
		m_width = 32.0f;
		m_height = 32.0f;
	};

	// This function is used for determining a general Collide
	// As long as there is something in the Contact List,
	// this function return true.
	bool Collide(){
		bool t_collide = false;
		//do{
		int t_size = m_PhysicObjectContactList.Get_Size();
		if(t_size > 0){
			t_collide = true;
			//break;
		}
		//}while(false);
		return t_collide;
	};

	// Used for checking for collision with a specific Physic Object 
	bool Contact(const PhysicObject *a_PhysicObject){
		bool t_collide = false;
		int t_size = m_PhysicObjectContactList.Get_Size();
		for(int i = 0; i < t_size; i++){
			if(a_PhysicObject == (*m_PhysicObjectContactList.Get_Data(i))){
				t_collide = true;
				break;
			}
		}
		return t_collide;
	};

	void Release(){
		m_PhysicObjectContactList.ClearPtr();
    }; 
};

// This is the Rigid Body. This is created and destroyed by the 
// Physic System. It should be used only by the Physic System. 
class PhysicRigidBody{
private:
	friend class PhysicSystem;
	friend class PhysicCollisionDetection;
	friend class PhysicCollisionResolution;

	PhysicObject *m_PhysicObject;
	
	LinkedList<PhysicRigidBody *> m_PhysicRigidBodyContactList;

	PhysicRigidBody(){
		m_PhysicObject = 0;
	};
	PhysicRigidBody(PhysicObject *a_PhysicObject){
		m_PhysicObject = a_PhysicObject;
	};

	void Release(){
		m_PhysicRigidBodyContactList.ClearPtr();
		m_PhysicObject = 0;
	};

public:
	~PhysicRigidBody(){}

};